# Specifické příkazy pro prostředí Google Colab
if 'google.colab' in str(get_ipython()):
import os, sys
os.chdir('/content')
# Stažení knihovny
! ls parlamentikon || git clone "https://github.com/parlamentikon/parlamentikon.git" --branch main
os.chdir('/content/parlamentikon/notebooks')
instalace_zavislosti = True
if instalace_zavislosti:
! pip install -r ../requirements.txt 1>/dev/null
instalace_knihovny = False
if instalace_knihovny:
! pip install .. 1>/dev/null
else:
# Přidání cesty pro lokální import knihovny
import sys, os
sys.path.insert(0, os.path.abspath('..'))
from datetime import datetime, timedelta
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import numpy as np
from parlamentikon.Hlasovani import Hlasovani, Omluvy
from parlamentikon.PoslanciOsoby import Poslanci
from nastav_notebook import nastav_pandas, clean_layout, clean_layout_with_x_spikes, clean_layout_with_y_spikes, clean_layout_with_xy_spikes, categorical_scale1
# nastavení výpisu, například zobrazení delších textů v sloupcích tabulek
nastav_pandas()
# formát výpisu data
format_den = "%d. %m. %Y"
# Data se budou pokaždé znovu stahovat z achivu PS
stahni=True
# Budeme analyzovat poslední volební období
zvolene_volebni_obdobi = None
# načti informace o poslancích (jméno, příjemní, za koho kandidovali, etc.)
p = Poslanci(stahni=stahni)
p.head(2)
2021-09-20:03:21:28 INFO [utility.py:21] Stahuji 'https://www.psp.cz/eknih/cdrom/opendata/poslanci.zip'. 2021-09-20:03:21:31 WARNING [Snemovna.py:149] While merging 'funkce' with 'typ_funkce': Dropping ['nazev_typ_organ_cz__typ_funkce', 'typ_organ_obecny__typ_funkce', 'nazev_typ_organ_en__typ_funkce', 'id_typ_organ__typ_funkce', 'typ_id_typ_organ__typ_funkce'] because of abundance.
| id_poslanec | id_osoba | id_kraj | id_kandidatka | id_organ | web | ulice | obec | psc | ... | nazev_kraj_cz | zkratka_kraj | id_parlament | od_parlament | do_parlament | id_klub | nazev_klub_cz | zkratka_klub | od_klub | do_klub | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index | |||||||||||||||||||||
| 0 | 1521 | 5700 | 588 | 155 | 172 | <NA> | Vančurovo nám. 663 | Hradec Králové | 50002 | adameci@psp.cz | ... | Královéhradecký | HK | 172 | 2017-10-21 14:00:00+02:00 | NaT | 1295 | Poslanecký klub Občanské demokratické strany | ODS | 2017-10-24 00:00:00+02:00 | NaT |
| 1 | 1522 | 6254 | 581 | 1104 | 172 | <NA> | Dobronická 1257 | Praha 4 - Kunratice | 14800 | adamkovav@psp.cz | ... | Hlavní město Praha | PH | 172 | 2017-10-21 14:00:00+02:00 | NaT | 1292 | Poslanecký klub ANO 2011 | ANO | 2017-10-24 00:00:00+02:00 | NaT |
2 rows × 38 columns
# načti informace o jednotlivých hlasováních
h = Hlasovani(stahni=stahni)
h.head(2)
2021-09-20:03:21:32 INFO [utility.py:21] Stahuji 'https://www.psp.cz/eknih/cdrom/opendata/poslanci.zip'. 2021-09-20:03:21:33 INFO [utility.py:21] Stahuji 'https://www.psp.cz/eknih/cdrom/opendata/hl-2017ps.zip'.
| id_hlasovani | id_organ | schuze | cislo | bod | cas | pro | proti | zdrzel | nehlasoval | ... | kvorum | nazev_dlouhy | nazev_kratky | datum | bod__KAT | vysledek | druh_hlasovani | ma_zpochybneni | je_zmatecne | ma_stenozaznam | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 67018 | 172 | 1 | 1 | 3 | 13:53:00 | 191 | 0 | 5 | 0 | ... | 99 | Inf. o ustavení volební komise PS a volbě členů | <NA> | 2017-11-20 13:53:00+01:00 | normální | přijato | normální | False | True | False |
| 1 | 67019 | 172 | 1 | 2 | 3 | 13:53:00 | 194 | 0 | 4 | 0 | ... | 100 | Inf. o ustavení volební komise PS a volbě členů | <NA> | 2017-11-20 13:53:00+01:00 | normální | přijato | normální | False | False | False |
2 rows × 21 columns
# načti omluvy poslanců ze schůze PS
om = Omluvy(stahni=stahni)
om.head(2)
2021-09-20:03:21:39 INFO [utility.py:21] Stahuji 'https://www.psp.cz/eknih/cdrom/opendata/poslanci.zip'. 2021-09-20:03:21:40 WARNING [Snemovna.py:149] While merging 'funkce' with 'typ_funkce': Dropping ['nazev_typ_organ_cz__typ_funkce', 'typ_organ_obecny__typ_funkce', 'nazev_typ_organ_en__typ_funkce', 'id_typ_organ__typ_funkce', 'typ_id_typ_organ__typ_funkce'] because of abundance. 2021-09-20:03:21:41 INFO [utility.py:21] Stahuji 'https://www.psp.cz/eknih/cdrom/opendata/hl-2017ps.zip'. 2021-09-20:03:21:48 WARNING [Snemovna.py:149] While merging 'omluvy' with 'poslanci': Dropping ['id_organ__poslanci'] because of abundance.
| id_organ | id_poslanec | den__ORIG | od__ORIG | do__ORIG | od | do | den | id_osoba | id_kraj | ... | zkratka_kraj | id_parlament | od_parlament | do_parlament | id_klub | nazev_klub_cz | zkratka_klub | od_klub | do_klub | je_poslanec | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| index | |||||||||||||||||||||
| 21451 | 172 | 1554 | 20.11.2017 | <NA> | <NA> | NaN | NaN | 2017-11-20 00:00:00+01:00 | 5261 | 581 | ... | PH | 172 | 2017-10-21 14:00:00+02:00 | NaT | 1293 | Poslanecký klub Komunistické strany Čech a Moravy | KSČM | 2017-10-24 00:00:00+02:00 | NaT | True |
| 21452 | 172 | 1533 | 22.11.2017 | <NA> | <NA> | NaN | NaN | 2017-11-22 00:00:00+01:00 | 6002 | 590 | ... | V | 172 | 2017-10-21 14:00:00+02:00 | NaT | 1294 | Poslanecký klub České strany sociálně demokratické | ČSSD | 2017-10-27 00:00:00+02:00 | NaT | True |
2 rows × 46 columns
volebni_obdobi = h.volebni_obdobi
snemovna = h.snemovna
print(f"Poslanecká sněmovna bude analyzovaná pro volební období {volebni_obdobi}.")
Poslanecká sněmovna bude analyzovaná pro volební období 2017.
# Za hlasovací dny označujeme takové, během nichž se sešla Sněmovna a o něčem se hlasovalo.
# TODO: Existují dny, kdy se konala schůze PS, ale o ničem se nehlasovalo? Jak je najdeme?
minimalni_pocet_hlasovacich_dni = 30
hlasovaci_dny = pd.to_datetime(h.datum.dt.date.unique()).tz_localize(h.tzn)
pocet_hlasovacich_dni = len(hlasovaci_dny)
def fce_pocet_omluvenych_dni(id_poslanec):
return om[(om.je_poslanec) & (om.id_poslanec == id_poslanec)].den.dt.date.nunique()
p['pocet_omluvenych_dni'] = p.id_poslanec.apply(fce_pocet_omluvenych_dni).astype('Int64')
assert p[p['pocet_omluvenych_dni'] > pocet_hlasovacich_dni].index.size == 0, \
f"Chyba ve výpočtu. Počet omluvenych dní poslance musí být menší než {pocet_hlasovacich_dni}."
p['pocet_hlasovacich_dni'] = p.apply(lambda row:
len(hlasovaci_dny[(hlasovaci_dny >= row['od_parlament'])
& ((hlasovaci_dny <= row['do_parlament']) | pd.isna(row['do_parlament']))])
, axis=1).astype('Int64')
assert p[p['pocet_hlasovacich_dni'] > pocet_hlasovacich_dni].index.size == 0,\
f"Chyba ve výpočtu. Počet hlasovacích dní poslance musí být menší než {pocet_hlasovacich_dni}."
p['pomer_omluvenych_dni'] = p['pocet_omluvenych_dni'] / p['pocet_hlasovacich_dni']
assert p[
(p.pocet_hlasovacich_dni > minimalni_pocet_hlasovacich_dni)
& ((p['pomer_omluvenych_dni'] > 1) | (p['pomer_omluvenych_dni'] < 0))].index.size == 0,\
f"Chyba ve výpočtu. Poměr omluvených dní poslance musí být v intervalu [0, 1]]."
if pd.isna(h.snemovna.do_organ):
print(f"Sněmovna {volebni_obdobi} se začala scházet {snemovna.od_organ.strftime(format_den)}.")
if len(h) > 0:
print(f"Naposledy se hlasovalo {h.datum.sort_values().dt.strftime(format_den).iloc[-1]}.")
else:
print(f"Sněmovna {volebni_obdobi} se začala scházet {snemovna.od_organ.strftime(format_den)} a skončila {snemovna.do_organ.strftime(format_den)}.")
print(f"Hlasovalo se během {pocet_hlasovacich_dni} dní.")
Sněmovna 2017 se začala scházet 21. 10. 2017. Naposledy se hlasovalo 17. 09. 2021. Hlasovalo se během 319 dní.
print(f"Průměrný poměr omluvených dnů: {p[p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni].pomer_omluvenych_dni.mean():.2f}.")
print(f"Medián poměr omluvených dnů: {p[p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni].pomer_omluvenych_dni.median():.2f}.")
fig = go.Figure(go.Box(y=p[p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni].pomer_omluvenych_dni))
fig.show()
Průměrný poměr omluvených dnů: 0.41. Medián poměr omluvených dnů: 0.39.
fig = go.Figure()
for zkratka_klub in p.zkratka_klub.unique():
data = p[(p.zkratka_klub == zkratka_klub) & (p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni)]
fig.add_trace(go.Box(y=data.pomer_omluvenych_dni, name=zkratka_klub))
layout = go.Layout(
title="Poměr počtu omluvených dní ku počtu hlasovacích dní dle poslaneckého klubu (strany)",
xaxis=dict(title="Strany", type='category'),
yaxis=dict(title="Poměr omluvených dní")
)
fig.update_layout(clean_layout_with_x_spikes)
fig.update_layout(layout)
fig.show()
data = pd.DataFrame([])
for zkratka_klub in p.zkratka_klub.unique():
v = p[(p.zkratka_klub == zkratka_klub) & (p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni)].pocet_omluvenych_dni.sum()
data.loc[zkratka_klub, 'pocet_omluvenych_dni'] = v
fig = go.Figure()
fig.add_trace(go.Bar(x=data.index, y=data.pocet_omluvenych_dni))
layout = go.Layout(
title="Počet omluvených dní dle poslaneckého klubu (strany)",
xaxis=dict(title="Strany", type='category'),
yaxis=dict(title="Poměr omluvených dní")
)
fig.update_layout(clean_layout_with_y_spikes)
fig.update_layout(layout)
fig.show()
print(f"Průměrný počet omluvených dnů: {p[(p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni)].pocet_omluvenych_dni.mean():.1f}.")
print(f"Medián počtu omluvených dnů: {p[(p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni)].pocet_omluvenych_dni.median():.1f}.")
Průměrný počet omluvených dnů: 121.5. Medián počtu omluvených dnů: 119.0.
go.Figure(go.Histogram(x=p[(p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni)].pomer_omluvenych_dni))
go.Figure(go.Histogram(x=p[(p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni)].pocet_omluvenych_dni))
cnt = 10
print(f"Poslanci s nejmenším počtem dnů, během nichž se omluvali z hlasování PS.")
fields = ['id_poslanec', 'jmeno', 'prijmeni', 'pomer_omluvenych_dni', 'pocet_omluvenych_dni', 'pocet_hlasovacich_dni', 'zkratka_klub']
p[(p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni)].sort_values(by="pocet_omluvenych_dni")[fields].head(cnt)
Poslanci s nejmenším počtem dnů, během nichž se omluvali z hlasování PS.
| id_poslanec | jmeno | prijmeni | pomer_omluvenych_dni | pocet_omluvenych_dni | pocet_hlasovacich_dni | zkratka_klub | |
|---|---|---|---|---|---|---|---|
| index | |||||||
| 86 | 1608 | Vladimír | Koníček | 0.051282 | 4 | 78 | KSČM |
| 132 | 1654 | Robert | Pelikán | 0.297872 | 14 | 47 | ANO |
| 191 | 1713 | Veronika | Vrecionová | 0.116279 | 15 | 129 | ODS |
| 218 | 1740 | Libor | Hoppe | 0.411765 | 21 | 51 | ODS |
| 131 | 1653 | Mikuláš | Peksa | 0.172131 | 21 | 122 | Piráti |
| 216 | 1738 | Miroslav | Samaš | 0.500000 | 33 | 66 | ANO |
| 214 | 1736 | Jaroslava | Puntová | 0.535211 | 38 | 71 | ANO |
| 217 | 1739 | Pavel | Šindelář | 0.696429 | 39 | 56 | ODS |
| 215 | 1737 | Jan | Jakob | 0.628571 | 44 | 70 | TOP09 |
| 164 | 1686 | Martin | Stropnický | 0.714286 | 45 | 63 | ANO |
cnt = 10
print(f"Poslanci s největším počtem dnů, během nichž se omluvali z hlasování PS.")
fields = ['id_poslanec', 'jmeno', 'prijmeni', 'pomer_omluvenych_dni', 'pocet_omluvenych_dni', 'pocet_hlasovacich_dni', 'zkratka_klub']
p[(p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni)].sort_values(by="pocet_omluvenych_dni")[::-1][fields].head(cnt)
Poslanci s největším počtem dnů, během nichž se omluvali z hlasování PS.
| id_poslanec | jmeno | prijmeni | pomer_omluvenych_dni | pocet_omluvenych_dni | pocet_hlasovacich_dni | zkratka_klub | |
|---|---|---|---|---|---|---|---|
| index | |||||||
| 3 | 1524 | Andrej | Babiš | 0.811912 | 259 | 319 | ANO |
| 158 | 1680 | Karel | Schwarzenberg | 0.746082 | 238 | 319 | TOP09 |
| 101 | 1623 | Jana | Levová | 0.739812 | 236 | 319 | SPD |
| 161 | 1683 | Antonín | Staněk | 0.733542 | 234 | 319 | ČSSD |
| 12 | 1533 | Jiří | Běhounek | 0.699060 | 223 | 319 | ČSSD |
| 56 | 1578 | Jan | Hamáček | 0.642633 | 205 | 319 | ČSSD |
| 19 | 1541 | Jan | Birke | 0.611285 | 195 | 319 | ČSSD |
| 170 | 1692 | Julius | Špičák | 0.608150 | 194 | 319 | ANO |
| 81 | 1603 | Jiří | Kobza | 0.608150 | 194 | 319 | SPD |
| 130 | 1652 | Markéta | Pekarová Adamová | 0.598746 | 191 | 319 | TOP09 |
cnt = 10
print(f"Poslanci s nejmenším poměrem dnů, během nichž se omluvali z hlasování PS.")
fields = ['id_poslanec', 'jmeno', 'prijmeni', 'pomer_omluvenych_dni', 'pocet_omluvenych_dni', 'pocet_hlasovacich_dni', 'zkratka_klub']
p[(p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni)].sort_values(by="pomer_omluvenych_dni")[fields].head(cnt)
Poslanci s nejmenším poměrem dnů, během nichž se omluvali z hlasování PS.
| id_poslanec | jmeno | prijmeni | pomer_omluvenych_dni | pocet_omluvenych_dni | pocet_hlasovacich_dni | zkratka_klub | |
|---|---|---|---|---|---|---|---|
| index | |||||||
| 86 | 1608 | Vladimír | Koníček | 0.051282 | 4 | 78 | KSČM |
| 191 | 1713 | Veronika | Vrecionová | 0.116279 | 15 | 129 | ODS |
| 131 | 1653 | Mikuláš | Peksa | 0.172131 | 21 | 122 | Piráti |
| 32 | 1554 | Jiří | Dolejš | 0.241379 | 77 | 319 | KSČM |
| 107 | 1629 | Tomáš | Martínek | 0.247649 | 79 | 319 | Piráti |
| 41 | 1563 | Milan | Feranec | 0.253918 | 81 | 319 | ANO |
| 157 | 1679 | Jan | Schiller | 0.254032 | 63 | 248 | ANO |
| 97 | 1619 | Roman | Kubíček | 0.257053 | 82 | 319 | ANO |
| 190 | 1712 | Petr | Vrána | 0.259434 | 55 | 212 | ANO |
| 18 | 1540 | Stanislav | Berkovec | 0.260188 | 83 | 319 | ANO |
cnt = 10
print(f"Poslanci s největším poměrem dnů, během nichž se omluvali z hlasování PS.")
fields = ['id_poslanec', 'jmeno', 'prijmeni', 'pomer_omluvenych_dni', 'pocet_omluvenych_dni', 'pocet_hlasovacich_dni', 'zkratka_klub']
p[(p.pocet_hlasovacich_dni >= minimalni_pocet_hlasovacich_dni)].sort_values(by="pomer_omluvenych_dni")[::-1][fields].head(cnt)
Poslanci s největším poměrem dnů, během nichž se omluvali z hlasování PS.
| id_poslanec | jmeno | prijmeni | pomer_omluvenych_dni | pocet_omluvenych_dni | pocet_hlasovacich_dni | zkratka_klub | |
|---|---|---|---|---|---|---|---|
| index | |||||||
| 3 | 1524 | Andrej | Babiš | 0.811912 | 259 | 319 | ANO |
| 158 | 1680 | Karel | Schwarzenberg | 0.746082 | 238 | 319 | TOP09 |
| 101 | 1623 | Jana | Levová | 0.739812 | 236 | 319 | SPD |
| 161 | 1683 | Antonín | Staněk | 0.733542 | 234 | 319 | ČSSD |
| 212 | 1734 | Irena | Blažková | 0.719626 | 77 | 107 | ANO |
| 164 | 1686 | Martin | Stropnický | 0.714286 | 45 | 63 | ANO |
| 213 | 1735 | Jaroslav | Vymazal | 0.701031 | 68 | 97 | ODS |
| 12 | 1533 | Jiří | Běhounek | 0.699060 | 223 | 319 | ČSSD |
| 217 | 1739 | Pavel | Šindelář | 0.696429 | 39 | 56 | ODS |
| 207 | 1729 | Václav | Votava | 0.676056 | 144 | 213 | ČSSD |
print(f"Poslední běh notebooku: {datetime.now().strftime('%d.%m.%Y %H:%M:%S')}.")
Poslední běh notebooku: 20.09.2021 03:21:55.